#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>

void sys_error_check(const int ret, const char *msg)
{
    if (ret < 0)
    {
        perror(msg);
        exit(EXIT_FAILURE);
    }
}
void *read_from_client_then_write(void* clifd)
{
    int clientfd = *(int *)clifd;
    char *read_buf = malloc(sizeof(char)*1024);
    char *write_buf = malloc(sizeof(char)*1024);
    ssize_t n = 0, send_count = 0;
    while(n = recv(clientfd, read_buf, 1024, 0)){
        printf("received: %s from %d\n", read_buf, clientfd);
        sprintf(write_buf, "received %s", read_buf);
        send_count = send(clientfd, write_buf, 1024, 0);
        if(send_count < 0){
            perror("send failed");
        }
    }
    close(clientfd);
    free(read_buf);
    free(write_buf);
}
int main(int argc, char const *argv[])
{
    int sockfd, ret;
    struct sockaddr_in server_addr, client_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    memset(&client_addr, 0, sizeof(client_addr));
    server_addr.sin_family = AF_INET;
    // server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//与下一行同义
    inet_pton(AF_INET, "0.0.0.0", &server_addr.sin_addr);
    server_addr.sin_port = htons(56321);
    printf("connection start\n");
    // create
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    sys_error_check(sockfd, "creat socket failed");

    ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    sys_error_check(ret, "bind failed");

    ret = listen(sockfd, 128);
    sys_error_check(sockfd, "listen error");
    socklen_t len = sizeof(client_addr);
    // accept
    while (1)
    {
        int clifd = accept(sockfd, (struct sockaddr *)&client_addr, &len);
        sys_error_check(clifd, "accept");
        printf("accept %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        pthread_t pid_read, pid_write;
        pthread_create(&pid_read, NULL, read_from_client_then_write, (void *)&clifd);
        //等待结束但不能挂起
        pthread_detach(pid_read);
    }

    close(sockfd);
    return 0;
}
